iT邦幫忙

2017 iT 邦幫忙鐵人賽
DAY 18
2
自我挑戰組

Android初學筆記系列 第 18

Day 18 - 側滑選單DrawerLayout

  • 分享至 

  • xImage
  •  

側滑選單是從螢幕左側滑出的元件,跟Menu一樣可以放一些功能或頁面連結,而側滑選單有較大的可用空間,當您有三個以上的選單項目時不妨考慮用側滑選單來做。

http://ithelp.ithome.com.tw/upload/images/20170102/20103849Lv3PM2cPXM.png

加入dependencies

DrawerLayout也是Design Library提供的元件,在gradle加入這行

compile 'com.android.support:design:25.1.0'

建立DrawerLayout

修改activity_main.xml,將DrawerLayout擺在最外層,注意其特性是Layout內只能放兩個View,所以我們用一個Layout將主要內容包起來做為第一個View,第二個View即為選單本身

<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/drawerLayout"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <!-- 頁面主要內容,用一個Layout包著  -->
    <android.support.design.widget.CoordinatorLayout
        android:id="@+id/coordinatorLayout"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:paddingLeft="@dimen/activity_horizontal_margin"
        android:paddingRight="@dimen/activity_horizontal_margin">

        <android.support.v7.widget.RecyclerView
            android:id="@+id/recycler_view"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:clipToPadding="false"
            android:paddingBottom="72dp" />

        <android.support.design.widget.FloatingActionButton
            android:id="@+id/btnAdd"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="bottom|end"
            android:layout_margin="16dp"
            android:src="@drawable/ic_add"
            app:elevation="6dp"
            app:pressedTranslationZ="12dp" />

    </android.support.design.widget.CoordinatorLayout>

    <!-- 選單 -->
    <android.support.design.widget.NavigationView
        android:id="@+id/navigation_view"
        android:layout_width="240dp"
        android:layout_gravity="start"
        android:layout_height="match_parent"
        app:menu="@menu/drawer" />

</android.support.v4.widget.DrawerLayout>

選單NavigationView是專為DrawerLayout搭配使用的元件,用app:menu來設置選單要有那些項目,所以我們到menu資料夾新增一個drawer.xml,新增方式可參考Day17

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">

    <group android:checkableBehavior="single">
        <item
            android:id="@+id/action_home"
            android:checked="true"
            android:icon="@drawable/ic_pets"
            android:title="首頁" />

        <item
            android:id="@+id/action_help"
            android:icon="@drawable/ic_help"
            android:title="使用說明" />

        <item
            android:id="@+id/action_settings"
            android:icon="@drawable/ic_settings"
            android:title="設定" />

        <item
            android:id="@+id/action_about"
            android:icon="@drawable/ic_about"
            android:title="關於" />
    </group>

</menu>

選項用group包起來並將android:checkableBehavior設置為單選,這樣NavigationView會自動處理點選時的上色效果,同時只會有一個選項被上色

執行APP,在畫面左邊按住並往右拖曳就會出現選單了,很神奇的是我們只放了白色的Icon,NavigationView會自動轉成平常顯示的灰色和選中時的藍色,真是好棒棒
http://ithelp.ithome.com.tw/upload/images/20170102/20103849UGrdn1LNYC.png


點擊事件

要處理選項的點擊只要為NavigationView設置Listener就可以了

public class MainActivity extends AppCompatActivity {

    private DrawerLayout drawerLayout;
    private NavigationView navigation_view;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        drawerLayout = (DrawerLayout) findViewById(R.id.drawerLayout);
        navigation_view = (NavigationView) findViewById(R.id.navigation_view);

        // 為navigatin_view設置點擊事件
        navigation_view.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() {
            @Override
            public boolean onNavigationItemSelected(@NonNull MenuItem item) {

                // 點選時收起選單
                drawerLayout.closeDrawer(GravityCompat.START);

                // 取得選項id
                int id = item.getItemId();

                // 依照id判斷點了哪個項目並做相應事件
                if (id == R.id.action_home) {
                    // 按下「首頁」要做的事
                    Toast.makeText(MainActivity.this, "首頁", Toast.LENGTH_SHORT).show();
                    return true;
                }
                else if (id == R.id.action_help) {
                    // 按下「使用說明」要做的事
                    Toast.makeText(MainActivity.this, "使用說明", Toast.LENGTH_SHORT).show();
                    return true;
                }
                // 略..

                return false;
            }
        });
    }

與ActionBar整合

要讓使用者有更好的體驗,我們要讓ActionBar出現一個「三」的按鈕,點擊時就滑出選單,並且讓選單不被ActionBar遮住

在style.xml裡修改theme,改成NoActionBar
http://ithelp.ithome.com.tw/upload/images/20170102/20103849kZ6vD88Su9.png

修改activity_main,加上一個Toolbar元件,Toolbar比內建的ActionBar有更多功能,例如現在要做的與DrawerLayout整合即是

<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/drawerLayout"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <!-- 頁面主要內容,用一個Layout包著  -->
    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <android.support.v7.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            android:background="?attr/colorPrimary"
            android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
            android:elevation="4dp"/>

        <android.support.design.widget.CoordinatorLayout
            android:id="@+id/coordinatorLayout"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_below="@+id/toolbar"
            android:paddingLeft="@dimen/activity_horizontal_margin"
            android:paddingRight="@dimen/activity_horizontal_margin">

            // 略..

        </android.support.design.widget.CoordinatorLayout>

    </RelativeLayout>

    <!-- 選單 -->
    <android.support.design.widget.NavigationView
        android:id="@+id/navigation_view"
        android:layout_width="240dp"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        android:fitsSystemWindows="true"
        app:menu="@menu/drawer"
        app:headerLayout="@layout/navigation_header"/>

</android.support.v4.widget.DrawerLayout>

程式碼處設置Toolbar和DrawerLayout整合,就會出現「三」的按鈕了

public class MainActivity extends AppCompatActivity {

    private DrawerLayout drawerLayout;
    private NavigationView navigation_view;
    private Toolbar toolbar;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        drawerLayout = (DrawerLayout) findViewById(R.id.drawerLayout);
        navigation_view = (NavigationView) findViewById(R.id.navigation_view);
        toolbar = (Toolbar) findViewById(R.id.toolbar);

        // 用toolbar做為APP的ActionBar
        setSupportActionBar(toolbar);

        // 將drawerLayout和toolbar整合,會出現「三」按鈕
        ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
                this, drawerLayout, toolbar, R.string.drawer_open, R.string.drawer_close);
        drawerLayout.addDrawerListener(toggle);
        toggle.syncState();
        
        // 下略...
    }

當中的R.String.drawer_open是用來表示選單目前是開啟或關閉,要寫在string.xml裡
http://ithelp.ithome.com.tw/upload/images/20170102/20103849nDXuXJxuwZ.png

執行APP,左上角「三」的漢堡圖案點了就會滑出選單
http://ithelp.ithome.com.tw/upload/images/20170102/201038494tAHW2BEWa.png


增加Header

NavigationView可以放自訂的header,只要建好header的xml並設置給NavigationView就可以了

在layout資料夾建立navigation_header.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="160dp"
    android:background="@color/colorPrimary"
    android:gravity="bottom"
    android:orientation="vertical"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin">

    <ImageView
        android:layout_width="64dp"
        android:layout_height="64dp"
        android:contentDescription="@null"
        android:src="@drawable/ic_pets" />

    <TextView
        android:id="@+id/txtHeader"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:ellipsize="end"
        android:paddingTop="4dp"
        android:text="唯一支持奶油臘腸"
        android:textColor="#ffffff" />

</LinearLayout>

activity_main.xml中的NavigationView加上app:headerLayout
http://ithelp.ithome.com.tw/upload/images/20170102/20103849Jm6F16kJzO.png

執行結果
http://ithelp.ithome.com.tw/upload/images/20170102/2010384935UszjbdFS.png

若之後要透過程式修改Header內容:

// 取得Header
View header = navigation_view.getHeaderView(0);
// 取得Header中的TextView
TextView txtHeader = (TextView) header.findViewById(R.id.txtHeader);
txtHeader.setText("123");

與StatusBar整合

Android 5.0之後可以在選單滑出時讓最上面的StatusBar變成半透明

values資料夾中新增styles(v21),已經有的就跳過
http://ithelp.ithome.com.tw/upload/images/20170102/20103849AWBcej9QEa.png

檔名為styles,選擇Version並按箭頭
http://ithelp.ithome.com.tw/upload/images/20170102/201038495FTNujAtdA.png

Platform API Level輸入21,按OK
http://ithelp.ithome.com.tw/upload/images/20170102/20103849Ww0PKN2v9N.png

在styles(v21)加入兩個屬性
http://ithelp.ithome.com.tw/upload/images/20170102/20103849iGACC19wjA.png

activity_main的最外層Layout加上android:fitSystemWindows
http://ithelp.ithome.com.tw/upload/images/20170102/20103849ocK2TAHcWa.png

執行APP,選單滑出時最上面StatusBar會變成半透明的
http://ithelp.ithome.com.tw/upload/images/20170102/20103849PWdwQEBioP.png


DrawerLayout相對於單調的Menu會有比較好的擴充性和視覺效果,頁面比較多的APP如Gmail和Telegram都把側滑選單運用得很好,雖然建立時多了一點步驟但在多頁面切換時會是很好的選擇哦

今天的專案:https://github.com/IvanBean/Day18 ,裡面有Day13累積至今的內容可以參考


上一篇
Day 17 - 建立選單(Menu)
下一篇
Day 19 - ButterKnife簡化程式碼
系列文
Android初學筆記30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言